home *** CD-ROM | disk | FTP | other *** search
/ Whiteline: Alpha / Whiteline Alpha.iso / linux / atari / source / source.lzh / atari-linux-0.01pl3 / drivers / block / floppy.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-08  |  14.1 KB  |  647 lines

  1. /*
  2.  *  linux/kernel/blk_drv/floppy.c
  3.  *
  4.  *  Copyright (C) 1993  Greg Harp
  5.  *  Atari Support by Björn Brauel
  6.  *
  7.  */
  8.  
  9. #include <linux/config.h>
  10. #include <linux/sched.h>
  11. #include <linux/fs.h>
  12. #include <linux/fcntl.h>
  13. #include <linux/kernel.h>
  14. #include <linux/timer.h>
  15. #include <linux/fdreg.h>
  16. #include <linux/fd.h>
  17. #include <linux/errno.h>
  18. #include <linux/types.h>
  19. #include <linux/delay.h>
  20. #include <linux/interrupt.h>
  21. #include <linux/mm.h>
  22. #include <asm/system.h>
  23.  
  24. #include <linux/atarihw.h>
  25. #include <linux/atariints.h>
  26.  
  27. #define MAJOR_NR FLOPPY_MAJOR
  28. #include "blk.h"
  29.  
  30. #undef __notneeded__
  31.  
  32. /*
  33.  *  Defines
  34.  */
  35. #define MAX_SECTORS    22
  36. #define RAW_BUF     900000
  37.  
  38. /*
  39.  *  Error codes
  40.  */
  41. #define FD_OK        0    /* operation succeeded */
  42. #define FD_ERROR    -1    /* general error (seek, read, write, etc) */
  43. #define FD_NOUNIT    1    /* unit does not exist */
  44. #define FD_UNITBUSY    2    /* unit already active */
  45. #define FD_NOTACTIVE    3    /* unit is not active */
  46. #define FD_NOTREADY    4    /* unit is not ready (motor not on/no disk) */
  47.  
  48. /*
  49.  *  Floppy ID values
  50.  */
  51. #define FD_NODRIVE    0x00000000  /* response when no unit is present */
  52. #define FD_HD_3     0xaaaaaaaa  /* high-density 3.5'' (1760K) drive */
  53. #define FD_DD_3     0xbbbbbbbb  /* high-density 3.5'' (880K) drive */
  54.  
  55.  
  56. /* Atari: Auto probing not implemented yet! If CONFIG_FLOPPY_DD_ONLY
  57.  * is not defined, all accesses are done for a HD disk.
  58.  */
  59.  
  60. /* For Atari, fields rdsz, wrsz, sm, pc1, pc2, sd, st, st unused */
  61.  
  62. static struct fd_drive_type drive_types[] = {
  63. /*  code    name       tr he   rdsz   wrsz sm pc1 pc2    sd     st    st*/
  64.  { FD_HD_3,    "HD 3.5", 160, 2, 25000, 25000, 2, 80,161, 3000, 18000, 1000},
  65.  { FD_DD_3,    "DD 3.5", 160, 2, 25000, 25000, 1, 80,161, 3000, 18000, 1000},
  66.  { FD_NODRIVE, "No Drive",  0, 0,     0,     0, 0,  0,  0,    0,     0,    0}
  67. };
  68. #ifdef __notneeded__
  69. static int num_dr_types = sizeof(drive_types) / sizeof(drive_types[0]);
  70. #endif
  71.  
  72. static struct fd_data_type data_types[] = {
  73.   { "Atari", 9 }
  74. };
  75. #ifdef __notneeded__
  76. static int num_da_types = sizeof(data_types) / sizeof(data_types[0]);
  77. #endif
  78.  
  79.  
  80. /* current info on each unit */
  81. static struct floppy_struct unit[FD_MAX_UNITS];
  82.  
  83. /* track buffer */
  84. int savedtrack = -1;
  85. unsigned char trackdata[512];
  86.  
  87. /*
  88.  * These are global variables, as that's the easiest way to give
  89.  * information to interrupts. They are the data used for the current
  90.  * request.
  91.  */
  92. char block_flag = 0;
  93. int selected = 0;
  94. struct wait_queue *wait_on_floppy_select = NULL;
  95. struct wait_queue *wait_fd_block = NULL;
  96.  
  97. /* Synchronization of FDC access. */
  98. #ifdef __notneeded__
  99. static volatile int fdc_busy = 0;
  100. static struct wait_queue *fdc_wait = NULL;
  101. static struct wait_queue *motor_wait = NULL;
  102. #endif
  103.  
  104. #if 0
  105. static unsigned int changed_floppies = 0;
  106. #endif
  107.  
  108. /*======================================================================
  109.   Select the side to use for a particular drive.
  110.   The drive must have been calibrated at some point before this.
  111.   The drive must also be active and the motor must be running.
  112. ======================================================================*/
  113. #ifdef __notneeded__
  114. static void fd_select_side(int drive, int side)
  115. {
  116.   unsigned long flags;
  117.  
  118.   save_flags(flags);
  119.   cli();
  120.   
  121.   if(side==0)
  122.    {
  123.     sound_ym.rd_data_reg_sel=14; /* Select PSG Port A */
  124.     sound_ym.wd_data = sound_ym.rd_data_reg_sel | 0x01;
  125.    }
  126.   else
  127.    {
  128.     sound_ym.rd_data_reg_sel=14; /* Select PSG Port A */
  129.     sound_ym.wd_data = sound_ym.rd_data_reg_sel & 0xfe;
  130.    }
  131.  
  132.    restore_flags(flags);
  133. }
  134. #endif
  135.  
  136.  
  137. #ifdef __notneeded__
  138. static struct timer_list motor_on_timer;
  139. static struct timer_list motor_off_timer[FD_MAX_UNITS];
  140. static int on_attempts;
  141. #endif
  142.  
  143. static void wait_func(void)
  144.  {
  145.   int i;
  146.   for(i=0;i<30;i++)
  147.    i=i;
  148.  }  
  149.  
  150. static void fd_select (int drive,unsigned short tr)
  151. {
  152.   int oldtr;
  153.   unsigned long flags;
  154.   unsigned char tmp;
  155.   
  156.   if (drive == selected)
  157.       return;
  158.   oldtr=tr/2;
  159.   selected = drive;
  160.  
  161.   save_flags(flags);
  162.   cli();
  163.  
  164.   if(oldtr*2==tr)
  165.    {
  166.     sound_ym.rd_data_reg_sel=14;    /* Select PSG Port A */
  167.     tmp = sound_ym.rd_data_reg_sel;
  168.     sound_ym.wd_data = tmp & ~2;    /* Select Side 0 and Drive A */
  169.    }
  170.   else
  171.    {
  172.     sound_ym.rd_data_reg_sel=14;    /* Select PSG Port A */
  173.     tmp = sound_ym.rd_data_reg_sel;
  174.     sound_ym.wd_data = tmp & ~3;    /* Select Side 1 and Drive A */
  175.    }
  176.  
  177.   restore_flags(flags);
  178. }
  179.  
  180. static void fd_deselect (int drive)
  181. {
  182.   unsigned long flags;
  183.  
  184.   if (drive != selected)
  185.       return;
  186.  
  187.   save_flags(flags);
  188.   cli();
  189.   sound_ym.rd_data_reg_sel=14; /* Select PSG Port A */
  190.   sound_ym.wd_data = sound_ym.rd_data_reg_sel | 7; /* no drives selected */
  191.   restore_flags(flags);
  192.  
  193.   selected=-1;
  194. }
  195.  
  196. static void fd_nobusy(void)
  197. {
  198.  unsigned char fd_status;
  199.  
  200.  do
  201.    fd_status = mfp.par_dt_reg & 0x20;
  202.  while(fd_status != 0);
  203.  
  204. }
  205.  
  206. /*======================================================================
  207.   Seek the drive to track 0.
  208.   The drive must be active and the motor must be running.
  209.   Returns standard floppy error code.
  210. ======================================================================*/
  211. #ifdef __notneeded__
  212. static int fd_calibrate(int drive)
  213. {
  214.  
  215.   fd_select(drive,0);
  216.   dma_wd.dma_mode_status=FDCSELREG_STP;
  217.   dma_wd.fdc_acces_seccount=FDCCMD_RESTORE | FDCCMDADD_V ;
  218.   
  219.   fd_nobusy();
  220.   fd_deselect(drive);
  221.   
  222.     return 1;
  223. }
  224. #endif
  225.  
  226. /*======================================================================
  227.   Seek the drive to the requested cylinder.
  228.   The drive must have been calibrated at some point before this.
  229.   The drive must also be active and the motor must be running.
  230. ======================================================================*/
  231. static int fd_seek(unsigned short drive, unsigned short track)
  232. {
  233.   dma_wd.dma_mode_status=FDCSELREG_DTA;
  234.   nop();
  235.   dma_wd.fdc_acces_seccount=track;
  236.   wait_func();
  237.   dma_wd.dma_mode_status=FDCSELREG_STP;
  238.   nop();
  239.   dma_wd.fdc_acces_seccount=FDCCMD_SEEK | FDCCMDADD_V ;
  240.   wait_func();
  241.   fd_nobusy();
  242.     
  243.     return 1;
  244. }
  245.  
  246.  
  247. struct header {
  248.     unsigned char magic;
  249.     unsigned char track;
  250.     unsigned char sect;
  251.     unsigned char ord;
  252.     unsigned char labels[16];
  253.     unsigned long hdrchk;
  254.     unsigned long datachk;
  255. };
  256.  
  257.  
  258.  
  259. /*==========================================================================
  260.   atari_write converts track/labels data to raw track data
  261. ==========================================================================*/
  262. static void atari_write(int dr, unsigned short tr, unsigned short sec)
  263. {
  264.   unsigned long phys_secbuf,flags;
  265.   int i;
  266.     
  267.   sec=sec+1;
  268.   
  269.   phys_secbuf=VTOP((unsigned long)trackdata); /* DMA knows PhysAdr only ! */
  270.   
  271.   save_flags(flags);  
  272.   cli();
  273.   
  274.   fd_select(dr,tr);
  275.   
  276.   tr=tr/2;
  277.  
  278.   /* Setup head pos. */
  279.   fd_seek(dr,tr);
  280.  
  281.  
  282.   /* Setup DMA */
  283.   dma_wd.dma_lo=(unsigned char)phys_secbuf;
  284.   phys_secbuf = phys_secbuf >> 8;
  285.   dma_wd.dma_md=(unsigned char)phys_secbuf;
  286.   phys_secbuf = phys_secbuf >> 8;
  287.   dma_wd.dma_hi=(unsigned char)phys_secbuf;
  288.   
  289.  
  290.   /* Clear FIFO and switch DMA to read-mode ! */  
  291.   dma_wd.dma_mode_status=0x190;  
  292.   dma_wd.dma_mode_status=0x90;  
  293.   dma_wd.dma_mode_status=0x190;  
  294.  
  295.   /* Transmit only 1 Sector */
  296.   dma_wd.fdc_acces_seccount=0x01;
  297.   wait_func();  
  298.   
  299.   
  300.   dma_wd.dma_mode_status=FDCSELREG_SEC | 0x100 ;
  301.   nop();
  302.   dma_wd.fdc_acces_seccount=sec;   
  303.   wait_func();
  304.   
  305.   /* Start Write */
  306.   dma_wd.dma_mode_status=FDCSELREG_STP | 0x100 ;
  307.   nop();
  308.   dma_wd.fdc_acces_seccount=FDCCMD_WRSEC ;
  309.   wait_func();;      
  310.   
  311.   fd_nobusy();  /* Wait for IRQ 5 */
  312.   
  313.   restore_flags(flags);
  314.   
  315.   fd_deselect(dr);
  316.   
  317.   for(i=0;i<20000;i++)
  318.    {
  319.     i=i;
  320.    }
  321.  }
  322.  
  323. /*==========================================================================
  324.   atari_read reads a raw track of data into a track buffer
  325. ==========================================================================*/
  326. static int atari_read(int dr, unsigned short tr, unsigned short sec)
  327. {
  328.   unsigned long phys_secbuf,flags;
  329.     
  330.   phys_secbuf=VTOP((unsigned long)trackdata);
  331.   
  332.   sec=sec+1;
  333.   
  334.   save_flags(flags);  
  335.   cli();
  336.   
  337.   fd_select(dr,tr);
  338.   
  339.   tr=tr/2;
  340.   
  341.   /* Setup head pos. */
  342.   fd_seek(dr,tr);
  343.   
  344.  
  345.   /* Setup DMA */
  346.   dma_wd.dma_lo=(unsigned char)phys_secbuf;
  347.   phys_secbuf = phys_secbuf >> 8;
  348.   dma_wd.dma_md=(unsigned char)phys_secbuf;
  349.   phys_secbuf = phys_secbuf >> 8;
  350.   dma_wd.dma_hi=(unsigned char)phys_secbuf;
  351.   
  352.  
  353.   /* Clear FIFO and switch DMA to read-mode ! */  
  354.   dma_wd.dma_mode_status=0x90;  
  355.   dma_wd.dma_mode_status=0x190;  
  356.   dma_wd.dma_mode_status=0x90;  
  357.   /* Transmit only 1 Sector */
  358.   dma_wd.fdc_acces_seccount=0x01;
  359.   wait_func();
  360.   
  361.   dma_wd.dma_mode_status=FDCSELREG_SEC;
  362.   nop();
  363.   dma_wd.fdc_acces_seccount=sec;   
  364.   wait_func();
  365.   
  366.   /* Start READ */
  367.   dma_wd.dma_mode_status=FDCSELREG_STP;
  368.   nop();
  369.   dma_wd.fdc_acces_seccount=FDCCMD_RDSEC ;
  370.   wait_func();
  371.     
  372.   fd_nobusy();  /* Wait for IRQ 5 */
  373.   
  374.   restore_flags(flags);
  375.   
  376.   fd_deselect(dr);
  377.   
  378.     return 0;
  379. }
  380.  
  381. /*
  382.  * Note that MAX_ERRORS=X doesn't imply that we retry every bad read
  383.  * max X times - some types of errors increase the errorcount by 2 or
  384.  * even 3, so we might actually retry only X/2 times before giving up.
  385.  */
  386. #define MAX_ERRORS 12
  387.  
  388. /*
  389.  * The driver is trying to determine the correct media format
  390.  * while probing is set. rw_interrupt() clears it after a
  391.  * successful access.
  392.  */
  393. static int probing = 0;
  394.  
  395. /* Prevent "aliased" accesses. */
  396. static fd_ref[4] = { 0,0,0,0 };
  397. static fd_device[4] = { 0,0,0,0 };
  398.  
  399. /*
  400.  * Current device number. Taken either from the block header or from the
  401.  * format request descriptor.
  402.  */
  403. #define CURRENT_DEVICE (CURRENT->dev)
  404.  
  405. /* Current error count. */
  406. #define CURRENT_ERRORS (CURRENT->errors)
  407.  
  408. static void floppy_off (unsigned int nr)
  409. {
  410. }
  411.  
  412.  
  413.  
  414. /*
  415.  * floppy-change is never called from an interrupt, so we can relax a bit
  416.  * here, sleep etc. Note that floppy-on tries to set current_DOR to point
  417.  * to the desired drive, but it will probably not survive the sleep if
  418.  * several floppies are used at the same time: thus the loop.
  419.  */
  420. int floppy_change(struct buffer_head * bh)
  421. {
  422.     return 0;
  423. }
  424.  
  425. static __inline__ void copy_buffer(void *from, void *to)
  426. {
  427.   ulong *p1,*p2;
  428.   int cnt;
  429.  
  430.   p1 = (ulong *)from;
  431.   p2 = (ulong *)to;
  432.  
  433.   for (cnt = 0; cnt < 512/4; cnt++)
  434.     *p2++ = *p1++;
  435. }
  436.  
  437.  
  438. static void redo_fd_request(void)
  439. {
  440.     unsigned int block, track, sector;
  441.     int device, drive, cnt;
  442.     struct floppy_struct *floppy;
  443.     char *data;
  444.  
  445.   
  446.     if (CURRENT && CURRENT->dev < 0) return;
  447.  
  448.     repeat:
  449.     
  450.   if(!CURRENT)
  451.     return;
  452.  
  453.     if (MAJOR(CURRENT->dev) != MAJOR_NR)
  454.         panic(DEVICE_NAME ": request list destroyed");
  455.  
  456.     if (CURRENT->bh) {
  457.         if (!CURRENT->bh->b_lock)
  458.             panic(DEVICE_NAME ": block not locked");
  459.     }
  460.  
  461.     probing = 0;
  462.     device = MINOR(CURRENT_DEVICE);
  463.         
  464.     if (CURRENT_DEVICE == 0x200 ) {
  465.         /* manual selection */
  466.         drive = 0;
  467.         floppy = unit + drive;
  468.     } 
  469.      else
  470.     {
  471.      printk("Unknown Device !\n");
  472.      return;
  473.     }
  474.     
  475.     for (cnt = 0; cnt < 2; cnt++) {
  476.         block = CURRENT->sector + cnt;
  477.         if ((int)block > floppy->blocks) {
  478.             end_request(0);
  479.             goto repeat;
  480.         }
  481.  
  482.         track = block / floppy->dtype->sects;
  483.         sector = block - track * floppy->dtype->sects;
  484.         data = CURRENT->buffer + 512 * cnt;
  485.         
  486.  
  487.         switch (CURRENT->cmd) {
  488.           case READ:
  489.             atari_read(device,track,sector);
  490.             copy_buffer(trackdata,data);
  491.             break;
  492.  
  493.           case WRITE:
  494.             copy_buffer(data,trackdata);
  495.             atari_write(device,track,sector);
  496.             break;
  497.  
  498.           default:
  499.             printk("do_fd_request: unknown command\n");
  500.             end_request(0);
  501.             goto repeat;
  502.         }
  503.     }
  504.  
  505.     end_request(1);
  506.     goto repeat;
  507. }
  508.  
  509. void do_fd_request(void)
  510.     redo_fd_request();
  511. }
  512.  
  513. static int fd_ioctl(struct inode *inode, struct file *filp,
  514.             unsigned int cmd, unsigned long param)
  515. {
  516.     printk("fd_ioctl not yet implemented: %d\n", cmd);
  517.     return -EINVAL;
  518. }
  519.  
  520. /*======================================================================
  521.   Return unit ID number of given disk
  522. ======================================================================*/
  523. #ifdef __notneeded__
  524. static unsigned long get_drive_id(int drive)
  525. {
  526.     return FD_HD_3;
  527. }
  528. #endif
  529.  
  530. static void fd_probe(int drive)
  531. {
  532.     unit[drive].type = NULL;
  533.     if (drive != 0)
  534.         /* At the moment, only one floppy drive is supported */
  535.         return;
  536.  
  537. #ifdef CONFIG_FLOPPY_DD_ONLY
  538.     unit[drive].type = &drive_types[1]; /* DD */
  539. #else
  540.     unit[drive].type = &drive_types[0]; /* HD */
  541. #endif
  542.  
  543.     unit[drive].dtype = &data_types[0]; /* only one type */
  544.     unit[drive].track = -1;
  545.  
  546.     unit[drive].sects = unit[drive].dtype->sects * unit[drive].type->sect_mult;
  547.     unit[drive].blocks = unit[drive].type->heads * unit[drive].type->tracks *
  548.                          unit[drive].sects;
  549.  
  550.     unit[drive].disk = -1;
  551.     unit[drive].motor = 0;
  552.     unit[drive].busy = 0;
  553.     unit[drive].status = -1;
  554. }
  555.  
  556. static void config_types(void)
  557. {
  558.     int drive;
  559.  
  560.     printk("Probing floppy drive(s):\n");
  561.     for (drive = 0; drive < FD_MAX_UNITS; drive++) {
  562.         fd_probe(drive);
  563.         if (unit[drive].type != NULL)
  564.             printk("%d: %s\n", drive, unit[drive].type->name);
  565.     }
  566. }
  567.  
  568. /*
  569.  * floppy_open check for aliasing (/dev/fd0 can be the same as
  570.  * /dev/PS0 etc), and disallows simultaneous access to the same
  571.  * drive with different device numbers.
  572.  */
  573. static int floppy_open(struct inode *inode, struct file *filp)
  574. {
  575.   int drive;
  576.   int old_dev;
  577.  
  578.   drive = inode->i_rdev & 3;
  579.   old_dev = fd_device[drive];
  580.  
  581.   if (fd_ref[drive])
  582.     if (old_dev != inode->i_rdev)
  583.       return -EBUSY;
  584.  
  585.   fd_ref[drive]++;
  586.   fd_device[drive] = inode->i_rdev;
  587.  
  588.   if (old_dev && old_dev != inode->i_rdev)
  589.     invalidate_buffers(old_dev);
  590.  
  591.   if (filp && filp->f_mode)
  592.     check_disk_change(inode->i_rdev);
  593.  
  594.  
  595.   return 0;
  596. }
  597.  
  598. static void floppy_release(struct inode * inode, struct file * filp)
  599. {
  600.   sync_dev(inode->i_rdev);
  601.   if (!fd_ref[inode->i_rdev & 3]--) {
  602.     printk("floppy_release with fd_ref == 0");
  603.     fd_ref[inode->i_rdev & 3] = 0;
  604.   }
  605. }
  606.  
  607. static struct file_operations floppy_fops = {
  608.     NULL,            /* lseek - default */
  609.     block_read,        /* read - general block-dev read */
  610.     block_write,        /* write - general block-dev write */
  611.     NULL,            /* readdir - bad */
  612.     NULL,            /* select */
  613.     fd_ioctl,        /* ioctl */
  614.     NULL,            /* mmap */
  615.     floppy_open,        /* open */
  616.     floppy_release,     /* release */
  617.     block_fsync        /* fsync */
  618. };
  619.  
  620. #ifdef __notneeded__
  621. static void fd_block_done(struct intframe *fp, void *data)
  622. {
  623. }
  624. #endif
  625.  
  626. void floppy_init(void)
  627. {
  628.   int i;
  629.  
  630.   if (register_blkdev(MAJOR_NR,"fd",&floppy_fops)) {
  631.     printk("Unable to get major %d for floppy\n",MAJOR_NR);
  632.     return;
  633.   }
  634.   /* initialize variables */
  635.   selected = -1;
  636.  
  637.   for (i = 0; i < FD_MAX_UNITS; i++) {
  638.       unit[i].track = -1;
  639.   }
  640.  
  641.   /* blk_size[MAJOR_NR] = floppy_sizes; */
  642.   blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
  643.  
  644.   config_types();
  645. }
  646.